module("Util", package.seeall)
local tableConcat = table.concat
local tableInsert = table.insert
local stringRep = string.rep
local stringFormat= string.format
local type = type
local pairs = pairs
local tostring = tostring

function FormatTable(root)
    local cache = { [root] = "." }
    local space, deep = string.rep(' ', 2), 0
    local function _dump(t, name)
        local temp = {}
        for k, v in pairs(t) do
            local key = stringFormat("[%s]", tostring(k))
            -- 防止递归调用
            if cache[v] then
                tableInsert(temp, stringFormat("%s%s = [%s]\n", stringRep(space, deep + 1), key, cache[v]))
            elseif type(v) == "table" then
                deep = deep + 2
                local new_key = name.."." .. key
                cache[v] = new_key
                if "[.data]" ~= key then
                    tableInsert(temp, stringFormat("%s%s = %s\n%s", stringRep(space, deep - 1), key, stringRep(space, deep - 1), _dump(v, new_key), stringRep(space, deep - 1)))
                else
                    tableInsert(temp, stringFormat("%s\n", _dump(v, new_key)))
                end

                deep = deep - 2
            else
                tableInsert(temp, stringFormat("%s%s = [%s]\n", stringRep(space, deep + 1), key, tostring(v)))
            end
        end
        return tableConcat(temp)
    end

    return stringFormat("[%s] = {\n%s}", tostring(root), _dump(root, ""))
end


function IsEmpty(data)
    return data == nil or data == 0
end

local function table2str_recur(tab, seen, prevBlankSpace, blankSpace)
    if nil == tab then
        return "nil"
    end

    if type(tab) ~= 'table' then
        return tostring(tab)
    end

    if seen[tab] then
        return "self"
    else
        seen[tab] = tab
    end

    local result = "{\n"
    for k, v in pairs(tab) do
        local kStr
        if type(k) == 'number' then
            kStr = blankSpace .. "[" .. table2str_recur(k, seen, blankSpace, blankSpace .. "    ") .. "]"
        else
            kStr = blankSpace .. table2str_recur(k, seen, blankSpace, blankSpace .. "    ")
        end

        local vStr = table2str_recur(v, seen, blankSpace, blankSpace .. "    ")
        if type(v) == 'string' then
            result = result .. kStr .. " = \"" .. vStr .. "\",\n"
        else
            result = result .. kStr .. " = " .. vStr .. ",\n"
        end
    end

    return result .. prevBlankSpace .. "}"
end

--table to string
function Table2Str(mTable)
    local seen = {}
    return table2str_recur(mTable, seen, "", "")
end

-- todo leiicao 拷贝heroVO有bug
function DeepClone(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
            -- 解决环的问题
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end

    return _copy(object)
end

-- 浅拷�?
function Clone(origin)
    local dest = {}
    for key, value in pairs(origin) do
        dest[key] = value
    end
    return dest
end

--- 用于在客户端发送协议时将bool类型转换为整�?
function Bool2Int(boolVal)
    if boolVal == true then
        return 1
    end

    return 0
end

-- 格式化Lua对象
function FormatObject(luaObject)
    print(FormatTable(luaObject));
end

function ConsoleError(errorInfo)
    Console.Error(stringFormat("%s\n%s", errorInfo, debug.traceback()))
end

function ClearItemTable(itemTable)
    -- remove all item with id equals 0
    for i=#itemTable,1,-1 do
        if 0 == itemTable[i].ID then
            table.remove(itemTable, i)
        end
    end
end

function GetTableLen(tab)
	local count = 0
	for _,item in pairs(tab) do
		count = count + 1
	end
	return count
end

--_G.Str = Table2Str
_G.printt = Table2Str
function Hash(v,ext)
    local ch = 0
    local val = 0

    if(v) then
        for i=1,#v do
            ch = v:byte(i)
            if( ch >= 65 and ch <= 90 ) then
                ch = ch + 32
            end
            val = val*0.7 + ch  --0.7是加权
        end
    end
    val = val .. ''
    val = val:gsub("+","")
    val = val:gsub("%.","")


    if(ext)then
        return string.format('%s.%s',val,ext)
    else
        return string.format('%s',val)
    end
end

math.Clamp = function(var,down,up)
    if nil == var or nil == down or nil == up then
        return var
    end

    if var < down then
        var = down
    end

    if var > up then
        var = up
    end

    return var
end

function printf(str,...)
	if not CS.PlatformExport.IsInStandaloneOrEditor() then
		return
	end	
	
    print(debug.traceback(string.format(str,...)))
end


function printt(mTable, str)
    if str then
        print(debug.traceback(str .. ":" .. Table2Str(mTable)))
    else
        print(debug.traceback(Table2Str(mTable)))
    end
end

_G.printf = printf

_G.printt = printt

--- example
--function replaceFunc(nIndex,bPercentFormat)
--    local value = nIndex * 100
--    if bPercentFormat then
--        return value/100
--    end
--    return value
--end

function FormatString(str, replaceFunc)
    return string.gsub (str, "{(%d)(%%?)}", function (index,percent)
        if #percent > 0 then
            return replaceFunc(index,true)
        end
        return replaceFunc(index,false)
    end)
end
_G.FormatString = FormatString

-- 解析时间 , 用于表格配置,时间字符串中包含：类似这样的格式"2017-01-01 12:11:22"
function ParseTime(s)
    if nil == s then
        Console.Error("ParseTime Error: input is nil ")
        return nil
    end

	local y,m,d,h,mm,s = string.match(s, "(%d+)[^%d](%d+)[^%d](%d+)%s(%d+)[^%d](%d+)[^%d](%d+)");
	local t = { year = y, month = m, day = d, hour = h, min = mm, sec = s};
    --print("year : " .. y .. " month:" .. m .. " day:" .. d .. " hour:" .. h .. " min:" .. mm .. " sec:" .. s)
    local ok,result = pcall(os.time, t)
    if not ok then
        return nil
    end

    return result
end

_G.D = ParseTime

--- 检查某个字段是否存在
function CheckMsgData(msg, str)
    local bOK, err = pcall(function(msg, str)
        return msg[str]
    end)
    return bOK and err
end
_G.CheckMsgData = CheckMsgData

--- 替换换行空格
-- http://www.cnblogs.com/leoin2012/p/7162099.html
function ReplaceSpace(msg)
    if nil == msg or "" == msg then
        return ""
    end

    return string.gsub(msg, ' ', _ReplaceSpaceMethod)
end

--UFT8
function _ReplaceSpaceMethod(subStr)
    return "\194\160"
end

function FormatMsgString(msg)
    msg = ReplaceSpace(msg)
    msg = msg:gsub("\\n", "\n")
    msg = msg:gsub("\\t", "\t")
    return msg
end